#!/usr/bin/env python
import sys, socket, time, threading
import struct
import selectors
loglock = threading.Lock()


def log(msg):
    loglock.acquire()
    try:
        print('[%s]: \n%s\n' % (time.ctime(), msg.strip()))
        sys.stdout.flush()
    finally:
        loglock.release()
global frpc_conn
frpc_conn =None

def read_data(conn,mask):
    global frpc_conn
    while  conn and frpc_conn:
        try:
            data = conn.recv(1020)  # Should be ready
            fd = conn.fileno()
            data = struct.pack('i',fd) + data # 将fd编码并发送到frpc
        except IOError as err: # 非阻塞模式下调用 阻塞操作recv 如果没有数据会抛出异常
            # pass
            break

        if data:
            print('conn ', conn,'send data to frpc...')

            frpc_conn.send(data)
        else:
            print('closing', conn)
            break


def accept_connection(sock, mask):
    global i
    global connMap
    # global client_conn
    conn,addr = sock.accept()
    print(addr)
    # fd = conn.fileno()
    # connMap[fd]=conn # 使用fd可以通过socket.socket直接获取到socket 所以不再存储
    # connMap[addr]=i
    # i+=1
    # client_conn = conn
    print("客户端连接成功")
    conn.setblocking(False)
    # conn.setblocking(True)
    # 注册为可读套接字
    sel.register(conn,selectors.EVENT_READ,read_data)


def accept_frp_connection(sock, mask):
    print("frpc客户端连接成功")
    global frpc_conn
    frpc_conn,addr = sock.accept()
    frpc_conn.setblocking(False)
    # frpc_conn.setblocking(True)
    # 注册为可读套接字
    sel.register(frpc_conn,selectors.EVENT_READ,handle_recv)

def handle_recv(frpc_conn,mask):
    while frpc_conn:
        try:
            data = frpc_conn.recv(1024)  # Should be ready
            if data:
                fdno = struct.unpack('i', data[0:4])[0]  # 提取出客户端fd
                conn = socket.socket(fileno=fdno)
                print(conn)
                print('recv frpc data',data[5:])
                conn.send(data[4:])  # Hope it won't block
            else:
                # print('closing frpc to', conn)
                break
        except IOError as err: # 非阻塞模式下调用 阻塞操作recv 如果没有数据会抛出异常
            # sel.unregister(conn)
            # conn.close()
            pass
            break


sel = selectors.DefaultSelector()
global i
global connMap
global client_conn
i=0
connMap = dict()
client_conn = None
class Frps(threading.Thread):
    def __init__(self, port, targetport):
        threading.Thread.__init__(self)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.bind(('0.0.0.0', port))
        # 设置为非阻塞模式
        self.sock.setblocking(False)
        self.sock.listen(100)
        sel.register(self.sock,selectors.EVENT_READ,accept_connection)

        frpc_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        frpc_sock.bind(('0.0.0.0', targetport))
        # frpc_sock.setblocking(False)
        frpc_sock.listen(10)
        sel.register(frpc_sock,selectors.EVENT_READ,accept_frp_connection)

    def run(self):
        while True:
            events = sel.select()
            for key, mask in events:
                callback = key.data
                callback(key.fileobj, mask)


if __name__ == '__main__':
    print('Starting')
    # try:
    #     port = int(sys.argv[1])
    #     try:
    #         targetport = int(sys.argv[2])
    #     except IndexError:
    #         targetport = port
    # except (ValueError, IndexError):
    #     print('Usage: %s port targethost [targetport]' % sys.argv[0])
    #     sys.exit(1)

    # sys.stdout = open('forwaring.log', 'w')
    # Frps(port, targetport).start()
    Frps(7006, 9081).start()
